#include "Driver.h"
#include "Scanner.h"
#include "Parser.tab.h"

namespace LALG
{

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Driver
 *      Method:  Driver
 * Description:  Constrói um driver passando o arquivo de entrada do código-fonte
 *--------------------------------------------------------------------------------------
 */
Driver::Driver(const string& filename)
    : generator(errors)
{
    this->filename = filename;

    istream.open(filename.c_str());
    if(!istream.good())
    {
        cerr << "Couldn't open file " << filename << endl;
        exit(EXIT_FAILURE);
    }

    scanner = new Scanner(*this);
    parser = new Parser(*this);
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Driver
 *      Method:  Driver
 * Description:  Destrói o driver
 *--------------------------------------------------------------------------------------
 */
Driver::~Driver()
{
    delete scanner;
    delete parser;
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Driver
 *      Method:  parse
 * Description:  Faz o parseamento
 *--------------------------------------------------------------------------------------
 */
bool Driver::parse(const string &out)
{
    auto ret = parser->parse();

    ofstream of(out);
    generator.generate(of);

    cout << "Done" << endl;
    return (ret == 0);
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Driver
 *      Method:  saveCurrent
 * Description:  Salva a linha e o token atual
 *--------------------------------------------------------------------------------------
 */
void Driver::saveCurrent()
{
    savedLine = scanner->getLineno();
    savedToken = scanner->getToken();
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Driver
 *      Method:  saveLine
 * Description:  Salva a linha atual
 *--------------------------------------------------------------------------------------
 */
void Driver::saveLine()
{
    ruleLine = scanner->getLineno();
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Driver
 *      Method:  lexError
 * Description:  Imprime um erro léxico
 *--------------------------------------------------------------------------------------
 */
void Driver::lexError(ErrorWhat what, string text)
{
    errors.print(scanner->getLineno(), ERR_LEX, what, text);
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Driver
 *      Method:  sinError
 * Description:  Imprime um erro sintático
 *--------------------------------------------------------------------------------------
 */
void Driver::sinError(ErrorWhat what, int synToken)
{
    errors.print(savedLine, ERR_SIN, what, savedToken, synToken);
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Driver
 *      Method:  semError
 * Description:  Imprime um erro semântico
 *--------------------------------------------------------------------------------------
 */
void Driver::semError(ErrorWhat what, string text)
{
    errors.print(ruleLine, ERR_SEM, what, text);
}

}
